!> 蛙跳法测试
module test_seakeeping_predictor_corrector

    use testdrive, only: new_unittest, unittest_type, error_type, check
    use seakeeping_module, only: wp => sk_real_kind, predictor_corrector
    implicit none

    private
    public :: collect_predictor_corrector

contains

    subroutine collect_predictor_corrector(testsuite)
        type(unittest_type), intent(out), allocatable :: testsuite(:)

        allocate (testsuite, source=[ &
                  new_unittest('predictor_corrector', test_predictor_corrector) &
                  ])

    end subroutine collect_predictor_corrector

    subroutine test_predictor_corrector(error)
        type(error_type), allocatable, intent(out) :: error
        real(wp) :: x(6), dt, t
        integer :: i
        real(wp), parameter :: x0(*) = [0.0_wp, 0.0_wp, -4.9_wp, 0.0_wp, 0.0_wp, -9.79999924_wp]

        dt = 0.1_wp
        x = 0
        t = 0

        call predictor_corrector(func, t, x, dt, 10, 6)

        call check(error, t, 1.00_wp, more='predictor_corrector: t')
        if (allocated(error)) return

        do i = 1, 6
            call check(error, x(i), x0(i), more='predictor_corrector: x')
        end do

    contains

        !> 三维自由落体运动
        subroutine func(t, y, yp)
            real(wp), intent(in) :: y(:), t
            real(wp), intent(out) :: yp(:)

            yp = [y(4:6), 0.0_wp, 0.0_wp, -9.8_wp]

        end subroutine func

    end subroutine test_predictor_corrector

end module test_seakeeping_predictor_corrector
